<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    class Mypromise {
      constructor(executor){
        this.init(executor)
        this.status = 'pending'
        this.success = undefined
        this.thenHandle = undefined
        this.then = this.then
      }
      init(executor){
        try {
          executor(this.resolve.bind(this),this.reject.bind(this))
        } catch (error) {
          this.reject(error)
        }
      }
      reject(err){}
      resolve(value){
        if(this.status === 'pending'){
          this.status = 'resolved'
          this.success = value
          this.thenHandle && this.thenHandle()
        }
      }
      then(onResolved){
        let promiseInstance = new Mypromise((resolve,reject)=>{
          if(this.status === 'pending'){
            this.thenHandle = ()=>{
              let nextPromise = onResolved && onResolved(this.success)
              this.handleResolvePromise(promiseInstance,nextPromise,resolve,reject)
            }
          }

          if(this.status === 'resolved'){
            let nextPromise = onResolved && onResolved(this.success)
            this.handleResolvePromise(promiseInstance,nextPromise,resolve,reject)
          }
        })
        return promiseInstance
      }
      handleResolvePromise(promiseInstance,nextPromise,resolve,reject){
        if(promiseInstance === nextPromise){
          throw new Error('循环调用')
        }
        if(nextPromise){
          if(nextPromise instanceof Mypromise){
            nextPromise.then((res)=>{
              resolve(res)
            })
          }else{
            resolve(nextPromise)
          }
        }else{
          resolve && resolve(undefined)
        }
      }
    }

    Mypromise.all = function(promises){
      return  new Mypromise((resolve,reject)=>{
        let results = []
        promises.forEach((promise) => {
          promise
          .then(res=>{
            handleresults(res)
          })
        });
        function handleresults(payload){
          results.push(payload)
          if(results.length === promises.length){
            resolve(results)
          }
        }
      })
    }

    //test
    let pro = new Mypromise(function (resolve, reject) {
      setTimeout(function () {
        resolve(100)
      }, 3000)
    })
    function pro2() {
      return new Mypromise(function (resolve, reject) {
        setTimeout(function () {
          resolve(200)
        }, 3000)
      })
    }
    function pro3() {
      return new Mypromise(function (resolve, reject) {
        setTimeout(function () {
          resolve(300)
        }, 3000)
      })
    }

    Mypromise.all([pro,pro2(),pro3()]).then((res)=>{
      console.log(res);
    })

    // pro
    //   .then(function (res) {
    //     console.log('then', res)
    //     return pro2()
    //   })
    //   .then(res => {
    //     console.log('then2', res);
    //     return pro3()
    //   })
    //   .then(res => {
    //     console.log('then3', res);
    //     return 400
    //   })
    //   .then(res => {
    //     console.log('then4', res);
    //   })




  </script>
</body>

</html>